<?php
namespace App\Services\ThirdPayments\Recharge;

use App\Lib\PaymentMap;
use App\Lib\ThirdPartyMap;
use App\Models\RechargeOrder;
use App\Services\ThirdPayments\BankTraits\YITENGBankMap;
use App\Services\ThirdPayments\Contracts\Actions\HrefRedirectAction;
use App\Services\ThirdPayments\Contracts\Actions\HtmlPrintAction;
use App\Services\ThirdPayments\Contracts\Actions\QrCodeAction;
use App\Services\ThirdPayments\Contracts\QRCapable;
use App\Services\ThirdPayments\Contracts\RechargeBaseAbstract;
use App\Services\ThirdPayments\Contracts\WAPable;

class YITENGPayment extends RechargeBaseAbstract implements WAPable, QRCapable
{
    use YITENGBankMap;

    protected $gw_pay = 'http://www.yitengzf.com/gateway';
    protected $gw_query = 'http://www.yitengzf.com/gateway';

    public function callback(array $data)
    {
        // TODO: Implement callback() method.
        if ($this->veryCallbackSign($data)) {
            if ($data['status'] == 1) return true;
        }
        return false;
    }

    public function veryCallbackSign(array $data)
    {
        // TODO: Implement veryCallbackSign() method.
        $params = $data;
        ksort($params);
        unset($params['sign']);
        unset($params['sign_type']);
        $signStr = "";
        foreach ($params as $key => $value) {
            $signStr .= $key . '=' . $value . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        $sign = md5($signStr);
        if (strcasecmp($sign, $data['sign']) == 0) return true;
        return false;

    }

    public function getOrderNoFromCallback(array $data)
    {
        // TODO: Implement getOrderNoFromCallback() method.
        return $data['out_trade_no'];
    }

    public function getOrderAmtFromCallback(array $data)
    {
        // TODO: Implement getOrderAmtFromCallback() method.
        return $data['total_amount'];
    }

    public function getThirdNoFromCallback(array $data)
    {
        return $data['trade_no'];
    }

    /**
     * @return mixed
     */
    public function getIdentify(): string
    {
        // TODO: Implement getIdentify() method.
        return ThirdPartyMap::YITENG;
    }

    /**
     *  needs child to achieve
     */
    public function initPaymentMap(): array
    {
        // TODO: Implement initPaymentMap() method.
        return [
            PaymentMap::BANK => 'gateway',
            PaymentMap::WX => 'weixin',
            PaymentMap::WX_WAP => 'wxh5',
            PaymentMap::ALI => 'alipay',
            PaymentMap::ALI_WAP => 'alipaywap',
            PaymentMap::QQ => 'qqqb',
            PaymentMap::QQ_WAP => 'qqrcode',
        ];
    }

    public function query(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement query() method.
        $content = json_encode(['out_trade_no' => $rechargeOrder->plat_no]);
        $this->setParameter('method', 'query');
        $this->setParameter('app_id', $this->getMchId());
        $this->setParameter('version', '1.0');
        $this->setParameter('content', $content);
        $this->setParameter('sign', $this->querySign());
        $this->setParameter('sign_type', 'MD5');
        $res = curlHttp($this->getGwQuery(), $this->getParameters(), 'post');
        if ($res['http_code'] == 200) {
            $body = json_decode($res['body'], true);
            return $body['errMsg'];
        }
        return 'curl 错误 ：' . $res['body'];
    }

    public function bankHref(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement bankHref() method.
        $paydata = $this->getPayData($rechargeOrder);
        $res = curlHttp($this->getGwPay(), $paydata, 'post');
        if ($res['http_code'] == 200) {
            $body = json_decode($res['body'], true);
            return $body['pay_url'];
        }
    }

    public function scanCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement scanCode() method.
        $paydata = $this->getPayData($rechargeOrder);
        return $this->getGwPay() . '?' . http_build_query($paydata);
    }

    public function paySign(): string
    {
        // TODO: Implement paySign() method.
        $data = $this->getParameters();
        $method = $this->getParameter('method');
        unset($data['method']);
        $content = $this->getContent($data);
        $sysParams["app_id"] = $this->getMchId();
        $sysParams["version"] = '1.0';
        $sysParams['method'] = $method;

        //获取业务参数
        $apiParams = $content;

        //签名
        $sysParams = array_merge($apiParams, $sysParams);//合并数组
        //加密签名时不需要sign和sign_type
        ksort($sysParams);
        $signStr = "";
        foreach ($sysParams as $key => $param) {
            $signStr .= $key . '=' . $param . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        $sysParams["sign"] = md5($signStr);//加密
        $sysParams["sign_type"] = "MD5";
        return $sysParams;
    }

    public function querySign(): string
    {
        // TODO: Implement querySign() method.
        $params = $this->getParameters();
        ksort($params);
        $signStr = "";
        foreach ($params as $key => $param) {
            $signStr .= $key . '=' . $param . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        return md5($signStr);//加密
    }

    public function showSuccess(): string
    {
        // TODO: Implement showSuccess() method.
        return 'success';
    }

    public function initParameters(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement initParameters() method.
        $mchData = $rechargeOrder->order_data;
        $this->setParameter('out_trade_no', $rechargeOrder->plat_no);
        $this->setParameter('total_amount', $rechargeOrder->order_amt);
        $this->setParameter('order_name', array_key_exists('body', $mchData) ? $mchData['body'] : '会员充值');
        $this->setParameter('spbill_create_ip', request()->getClientIp());
        $this->setParameter('notify_url', $this->getCallbackUrl());
        $this->setParameter('return_url', $this->getReturnUrl());
        $this->setParameter('method', $this->getPaymentMap($mchData['recharge_type']));
        if (PaymentMap::isBankHref($mchData['recharge_type'])) {
            $this->setParameter('channel_type', '07');
            $this->setParameter('subject', $this->getParameter('order_name'));
            $this->setParameter('bank_code', $this->getBank($mchData['bank_code']));
        }

    }

    public function getPayData($rechargeOrder)
    {

        $this->initParameters($rechargeOrder);
        // TODO: Implement paySign() method.
        $data = $this->getParameters();
        $method = $this->getParameter('method');
        unset($data['method']);
        $content = $this->getContent($data);
        $sysParams["app_id"] = $this->getMchId();
        $sysParams["version"] = '1.0';
        $sysParams['method'] = $method;

        //获取业务参数
        $apiParams = $content;

        //签名
        $sysParams = array_merge($apiParams, $sysParams);//合并数组
        //加密签名时不需要sign和sign_type
        ksort($sysParams);
        $signStr = "";
        foreach ($sysParams as $key => $param) {
            $signStr .= $key . '=' . $param . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        $sysParams["sign"] = md5($signStr);//加密
        $sysParams["sign_type"] = "MD5";
        return $sysParams;
    }

    public function getContent($data)
    {
        return ['content' => json_encode($data)];
    }

    public function qrCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement qrCode() method.
        $paydata = $this->getPayData($rechargeOrder);
        $res = curlHttp($this->getGwPay(), $paydata, 'post');
        if ($res['http_code'] == 200) {
            $body = json_decode($res['body'], true);
            return new QrCodeAction($body['qr_code']);
        }
        return new QrCodeAction('取码异常');
    }

    public function wapReq(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement wapReq() method.
        $paydata = $this->getPayData($rechargeOrder);
        return new HrefRedirectAction($this->getGwPay() . '?' . http_build_query($paydata));
    }
}
